package com.bigfans.framework.jms;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageListener;

import com.bigfans.framework.utils.ReflectionUtils;

public class JmsReceiverTemplate {

	private ConnectionFactory connectionFactory;
	private Executor executor;
	private Map<String, JmsReceiverTask> taskPool;
	private Map<String , MessageListener> receivers;
	
	public JmsReceiverTemplate(JmsConnectionFactory connectionFactory) {
		this.connectionFactory = connectionFactory;
		this.receivers = new HashMap<String , MessageListener>();
	}

	public ConnectionFactory getConnectionFactory() {
		return connectionFactory;
	}

	public void setConnectionFactory(ConnectionFactory connectionFactory) {
		this.connectionFactory = connectionFactory;
	}
	
	public Map<String, MessageListener> getMessageReceivers() {
		return receivers;
	}
	
	public void registerReceiver(MessageReceiver messageReceiver){
		List<Method> receivers = ReflectionUtils.getMethodsWithAnnotation(messageReceiver.getClass(), JmsMessageListener.class);
		for(Method receiver : receivers){
			JmsMessageListener annotation = receiver.getAnnotation(JmsMessageListener.class);
			String destination = annotation.destination();
			MessageListener listener = new MethodMessageListener(messageReceiver , receiver);
			this.receivers.put(destination, listener);
		}
	}
	
	public void startListen(){
		if(this.executor == null){
			this.executor = Executors.newFixedThreadPool(receivers.size());
		}
		try {
			for(Map.Entry<String , MessageListener> entry : receivers.entrySet()){
				Connection connection = connectionFactory.createConnection();
				JmsReceiverTask task = new JmsReceiverTask(connection, entry.getKey(), entry.getValue());
				this.executor.execute(task);
			}
		} catch (JMSException e) {
			e.printStackTrace();
		}
	}
	
	public void setMessageListeners(Map<String, MessageListener> receivers) {
		this.receivers = receivers;
	}
	
	public void destroy(){
		stopAll();
	}

	public void stop(String topic) {
		JmsReceiverTask task = taskPool.get(topic);
		task.stop();
	}

	public void stopAll() {
		for (Map.Entry<String, JmsReceiverTask> entry : taskPool.entrySet()) {
			JmsReceiverTask task = entry.getValue();
			task.stop();
		}
	}
}
